/**
 * 
 */
package sagroup.dracots.testing;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import lights.adapters.Field;
import lights.adapters.Tuple;
import lights.interfaces.ITuple;
import lime2.AgentCreationException;
import lime2.BootException;
import lime2.LimeServer;
import lime2.LimeTemplate;
import lime2.LimeTupleSpace;
import lime2.Location;

/**
 * Provide a runtime console to control Lime 2 system
 * 
 * @author Xing Jiankuan
 * 
 */
public class ControlConsole implements Runnable {

	private BufferedReader input = new BufferedReader(new InputStreamReader(
			System.in));

	private LimeServer server = LimeServer.getServer();

	public void run() {
		String cmd;
		String[] tokens = null;
		String[] paras = null;
		Thread.currentThread().setName("ControlConsole");
		LimeTupleSpace.get("testing").rdp(
				new LimeTemplate(Location.UNSPECIFIED, Location.UNSPECIFIED,
						new Tuple().add(new Field().setType(String.class)))); // start
		// the testing tuple space
		while (true) {
			System.out.print(server.getServerID().toString() + ">");
			try {
				cmd = input.readLine();
				tokens = cmd.split("(" + (char) 32 + "|" + (char) 9 + ")+");
				if (tokens[0].compareToIgnoreCase("load") == 0) {
					paras = new String[tokens.length - 2];
					System.arraycopy(tokens, 2, paras, 0, paras.length);
					if (!tokens[1].startsWith("sagroup.testing."))
						tokens[1] = "sagroup.testing." + tokens[1];
					server.loadAgent(tokens[1], paras);
				} else if (tokens[0].compareToIgnoreCase("add") == 0) {
					if (tokens.length != 2 && tokens.length != 4) {
						throw new Exception("Illegal command format");
					}
					performAdd(tokens);
				} else if (tokens[0].compareToIgnoreCase("boot") == 0) {
					server.boot();
				} else if (tokens[0].compareToIgnoreCase("shutdown") == 0) {
					server.shutdown(); // the whole system will be shut down,
										// any agent will be unloaded.
				} else if (tokens[0].compareToIgnoreCase("addr") == 0) {
					System.out.println("Unicast:"
							+ server.getUnicastAddress().getHostAddress() + "("
							+ server.getUnicastAddress().getHostName() + "):"
							+ server.getUnicastPort() + " Multicast:"
							+ server.getMulticastAddress() + ":"
							+ server.getMulticastPort());
				} else if (tokens[0].compareToIgnoreCase("help") == 0) {
					System.out
							.println("Usage:\n"
									+ "boot \"boot the lime server\"\n"
									+ "shutdown \"shut down the whole system\"\n"
									+ "addr \"show local address information\"\n"
									+ "load agent-qualified-name [parameter [parameter ...]] \"load an agent\""
									+ "add [ip] [port] count \"write tuples to somewhere for test\"\n");
				}
			} catch (IOException e) {
				e.printStackTrace();
			} catch (AgentCreationException e) {
				System.out.println("Unable to load agent:" + tokens[1]
						+ " with parameters:" + paras.toString());
			} catch (BootException e) {
				System.out.println(e.getMessage());
			} catch (Exception e) {
				System.out.println(e.getMessage());
			}
		}

	}

	// out specified number of tuples to a node
	private void performAdd(String[] tokens) {
		LimeTupleSpace ts = LimeTupleSpace.get("testing");
		if (tokens.length == 2) {
			// local case
			int count = Integer.parseInt(tokens[1]);
			for (int i = 0; i < count; i++) {
				ITuple t = new Tuple().add(new Field().setValue("localString"
						+ i));
				ts.out(Location.HERE, t);
			}
		} else {
			// remote case
			Location whereTo = Location.build(tokens[1], Integer
					.parseInt(tokens[2]));
			int count = Integer.parseInt(tokens[3]);
			for (int i = 0; i < count; i++) {
				ITuple t = new Tuple().add(new Field().setValue("remoteString"
						+ i));
				ts.out(whereTo, t);
			}
		}

	}

}
